package atributos;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author maldo
 */
public class ManagerAtributos {

    protected File folder;
    protected File folderAtrib;
    protected File[] listaArchivos;
    protected File[] listaAtrib;

    private ArrayList<PalClave> atribPers; //info del properties
    private ArrayList<Atributo> atribSistArc; //info del sis archivos

    final static String ARCH_PROP = "properties.dat";

    final static int POR_ID = 1;
    final static int POR_KW = 2;
    final static int POR_KM = 3;
    final static int POR_TD = 4;

    public static String PATH;

    public ManagerAtributos(String ruta)  {
        try {

            PATH = ruta;
            atribSistArc = new ArrayList<Atributo>();
            atribPers = new ArrayList<PalClave>();
            File file = new File(ARCH_PROP);
            if (!file.exists()) {
                try {
                    file.createNewFile();
                    atribPers.add(new PalClave("", ""));
                    guadarPalabrasClave();
                } catch (IOException ex) {
                    Logger.getLogger(ManagerAtributos.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else {
                try {
                    constAtribPers();
                } catch (IOException ex) {
                    Logger.getLogger(ManagerAtributos.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(ManagerAtributos.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            folder = new File(PATH);
            if (!folder.exists()) {
                System.out.println("No existe el folder de los archivos");
            }
            try {
                this.actualizarArchivos();
            } catch (FileNotFoundException ex) {
                Logger.getLogger(ManagerAtributos.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(ManagerAtributos.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (IOException ex) {
            Logger.getLogger(ManagerAtributos.class.getName()).log(Level.SEVERE, null, ex);
        }
  

    }

    public void construirListaArchivos(){
        String[] patron = {".mp3",".doc",".txt",".mpg",".avi","mpeg",".wav",".wma",".pdf",".docx"};
        Filter filtro = new Filter(patron);
        listaArchivos = folder.listFiles(filtro);
    }

    public void construirAtributos() throws IOException{
        Atributo atrib;
        String[] patron = {".atb"};
        Filter filtro = new Filter(patron);
        listaAtrib = folder.listFiles(filtro);
        System.out.println("El numero de atributos es: " + listaAtrib.length);
    }
    /**
    * Rellena el ArrayList atribSistArc con los atributos de los archivos
    * 
    * @param path ruta de la estructura de los archivos
    * @return El ArrayList de los atribPers obtenidos
    * @throws IOException
    */
    private void constAtribSistArc(File path) throws IOException {

        File[] listOfFiles = path.listFiles();

        Atributo att;

        for (int i = 0; i < listOfFiles.length; i++) {
            if (listOfFiles[i].isDirectory()) {
                constAtribSistArc(listOfFiles[i]);
            } else {
                att = new Atributo(listOfFiles[i]);
                atribSistArc.add(att);
            }
        }
    }

    /**
     * Almacena los objetos Atributo en un archivo definido como ARCH_PROP
     *
     * @param atribPers ArrayList de los atribPers
     * @throws FileNotFoundException
     * @throws IOException
     */
        private void guadarPalabrasClave() throws FileNotFoundException, IOException{
        File file = new File(ARCH_PROP);
        file.delete();
        file.createNewFile();
        FileOutputStream fos = new FileOutputStream(ARCH_PROP);
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        for (int i = 0; i < atribPers.size(); i++) {
                oos.writeObject(atribPers.get(i));
            }
        oos.flush();
        fos.flush();
        oos.close();
        fos.close();
    }

    /**
     * Construye un ArrayList de tipo Atributo a partir de los datos almacenados
     * en el archivo ARCH_PROP
     *
     * @return atribPers    ArrayList generado desde el archivo
     * @throws FileNotFoundException
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public void constAtribPers() throws IOException, ClassNotFoundException{
        
        PalClave pl = new PalClave();

        FileInputStream fis = new FileInputStream(ARCH_PROP);
        ObjectInputStream ois = new ObjectInputStream (fis);

        while (fis.available() != 0) {
            pl = (PalClave) ois.readObject();
            atribPers.add(pl);
        }
    }

    /**
     * Realiza un System.out.println de todos los atribPers que obtiene como
     * parametro
     * @param atribPers ArrayList de los objetos tipo Atributo
     */
    public void mostrarAtributos(ArrayList<Atributo> atributos){
        Atributo att;
        for(int i=0; i < atributos.size(); i++) {
            att = atributos.get(i);
            System.out.println(att.toString());
        }
    }

    /**
     * Retorna la carpeta donde están los archivos compartidos
     * @return carpeta tipo File
     */
    public  File getFolder(){
        return folder;
    }

    public void guardarAtributosDeEstructuraArchivos() throws IOException{
        this.guadarPalabrasClave();
    }

    /**
     *
     * @param tipo
     * @param query
     * @return
     */
    public ArrayList<Atributo> buscarAtributo(int tipo, String query){
        return null;
    }

    /**
     * Devueleve el archivo
     * @param ID
     * @return
     */
    public File getArchivo(String ID){
        return null;
    }
    /**
     * devuelve el ArrayList de los atribPers
     * @return
     */
    public ArrayList<PalClave> getPalClave() {
        return atribPers;
    }

    public void setPalClave(ArrayList<PalClave> pl) throws FileNotFoundException, IOException {
        this.atribPers = pl;
        this.guadarPalabrasClave();
    }
    /**
     * Construye el array temporal del los archivos del la estructura de compartidos
     * @return
     */
    public void actualizarArchivos() throws IOException, FileNotFoundException, ClassNotFoundException{
       // this.atribSistArc = null;

        this.constAtribSistArc(folder);

//        this.atribPers.clear();
     //   this.constAtribPers();

            //si salio un archivo de la carpeta
        boolean encontro;
        int tamanio=atribPers.size();
        for(int i=0; i<atribPers.size(); i++){
            encontro = false;
            for(Atributo a: atribSistArc){
                if(a.getId().equals(atribPers.get(i).getID())){
                    encontro =true;
                    a.setPalabrasClave(atribPers.get(i).getPalClave());
                    break;
                }
            }
            if(!encontro){
                    atribPers.remove(i);
                    i--;
            }
        }



        //nuevo archivo en la carpeta compartida
        for(Atributo a:atribSistArc){
            encontro = false;
            for(PalClave pl : atribPers){
                if(a.getId().equals(pl.getID())){
                    encontro = true;
                    a.setPalabrasClave(pl.getPalClave());
                    break;
                }
            }
            if(!encontro){
                PalClave palC = new PalClave(a.getId(), "");
                atribPers.add(palC);
            }
        }

        this.guadarPalabrasClave();
    }
   public void actualizarArchivos2() throws IOException, FileNotFoundException, ClassNotFoundException{
          constAtribPers();
        //  this.atribSistArc.clear();
          this.constAtribSistArc(folder);

//        this.atribPers.clear();
     //   this.constAtribPers();

            //si salio un archivo de la carpeta
        boolean encontro;
        int tamanio=atribPers.size();
        for(int i=0; i<atribPers.size(); i++){
            encontro = false;
            for(Atributo a: atribSistArc){
                if(a.getId().equals(atribPers.get(i).getID())){
                    encontro =true;
                    a.setPalabrasClave(atribPers.get(i).getPalClave());
                    break;
                }
            }
            if(!encontro){
                    atribPers.remove(i);
                    i--;
            }
        }



        //nuevo archivo en la carpeta compartida
        for(Atributo a:atribSistArc){
            encontro = false;
            for(PalClave pl : atribPers){
                if(a.getId().equals(pl.getID())){
                    encontro = true;
                    a.setPalabrasClave(pl.getPalClave());
                    break;
                }
            }
            if(!encontro){
                PalClave palC = new PalClave(a.getId(), "");
                atribPers.add(palC);
            }
        }

        this.guadarPalabrasClave();

    }
    /**
     * Devuelve el ArrayList con los objetos tipo Atributo
     * @return
     */
    public ArrayList<Atributo> getAtribSistArc() {
        return atribSistArc;
    }

    /**
     * Utilizado cuando actualiza los valores desde la interfaz
     * @param atribSistArc
     */
    public void setAtribSistArc(ArrayList<Atributo> atribSistArc) throws FileNotFoundException, IOException {
        this.atribSistArc = atribSistArc;
        this.atribPers.clear();

        for (Atributo a : atribSistArc) {
                this.atribPers.add(new PalClave(a.getId(), a.getPalabrasClave()));
            }
        guadarPalabrasClave();
    }


    public ArrayList<Atributo> Consulta(int tipo, String query,String nombrePeer) {

        ArrayList<Atributo> resultado = new ArrayList<Atributo>();
        Atributo temporal = null;
        boolean encontro = false;
        int index;
        int diferencia;
        int tamanioArchivo;
        int elegido;
        int buscado;

        if(tipo == POR_ID){
            for (Atributo a : atribSistArc) {
                if (a.getId().equals(query)) {
                    resultado.add(a);
                    mostrarAtributos(resultado);
                    return resultado;
                }
            }
        }else if(tipo == POR_KM){
            buscado = Integer.parseInt(query);
            if (!atribSistArc.isEmpty()) {
                elegido = Math.abs(Integer.parseInt(atribSistArc.get(0).getTamanio())- buscado);
                for (Atributo a : atribSistArc) {
                    tamanioArchivo = Integer.parseInt(a.getTamanio());
                    diferencia = Math.abs(tamanioArchivo - buscado);
                    if (diferencia <= elegido) {
                        temporal = a;
                        temporal.setNombrePeer(nombrePeer);
                        elegido = diferencia;
                    }
                }
                resultado.add(temporal);
                System.out.println("Resultado de la busqueda " + tipo);
                mostrarAtributos(resultado);
                return resultado;
            } else {
                return resultado;
            }
        }else if(tipo == POR_KW){
            for (Atributo a : atribSistArc) {
                if (a.toString().contains(query)) {
                    a.setNombrePeer(nombrePeer);
                    resultado.add(a);
                }
            }
            System.out.println("Resultado de la busqueda " + tipo);
            mostrarAtributos(resultado);
            return resultado;
        }else if (tipo == POR_TD){
            for (Atributo a : atribSistArc) {
                byte [] identificador = a.getId().getBytes();
                
                a.setNombrePeer(nombrePeer);              
                a.elmac = seguridad.Seguridad.mac.doFinal(identificador) ;
                resultado.add(a);              
             }
            System.out.println("Resultado de la busqueda " + tipo);
            mostrarAtributos(resultado);
            return resultado;  
        }

        return null;
    }
}
